/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pope.jloading;

import pope.jloading.downloader.Config;
import pope.jloading.downloader.ConfigFactory;
import pope.jloading.downloader.XmlOper;
import java.io.File;
import java.util.List;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import pope.jloading.Elog;
import pope.jloading.TaskManager;
import pope.jloading.TaskModel;
import pope.jloading.TaskTableModel;

public class TaskManager {
    private static TaskManager instance = new TaskManager();
    private TaskManager(){
        try {
            if (tasksFile == null) 
                tasksFile = new File("tasks.xml");
            if (!tasksFile.exists()) {
                tasksFile.createNewFile();
                doc = XmlOper.newDocument();
                Element eTasks = doc.createElement("tasks");
                doc.appendChild(eTasks);
                XmlOper.saveDocument(doc, tasksFile);
            } else {
                doc = XmlOper.getDocument(tasksFile);
            }
        } catch (Exception e) {
            Elog.log("处理任务列表文件时遇到错误:" + e.getMessage());
        }
    }
    
    public static TaskManager getInstance() {
        return instance;
    }
    
    private String sid;
    // 任务表格
    private JTable jTable;
    private TaskTableModel ttm;
    private Thread jTable_listener;
    
    /** 设置所监视的任务表格 */
    public void setTable(JTable table) {
        this.jTable = table;
        this.ttm = getTableModel();
        // 定时更新jTable1(每1000毫秒)
        jTable_listener = new Thread(new Runnable(){
            Runnable rp = new Runnable() {
                public void run() {
                    jTable.updateUI();
                }
            };
            public void run() {
                while (true) {
                    SwingUtilities.invokeLater(rp);
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }  
                }
            }
        });
        jTable_listener.start();
    }
    
    private TaskTableModel getTableModel() {
        TableModel tm = jTable.getModel();
        if (tm instanceof TaskTableModel) {
            return ((TaskTableModel) tm);
        }
        return null;
    }
    
    /**
     * 添加新的下载任务,方法同时生成一个唯一任务id
     * @param name 文件名
     * @param url 下载源
     * @param save 保存目录
     */
    public synchronized void addTask(String name, String url, String save) {
        String type = url.substring(url.lastIndexOf("."));
        if (null == save || "".equals(save)) {
            File musics = new File("idownloads");
            if (!musics.exists()) {
                musics.mkdirs();
            }
            save = musics.getAbsolutePath();
        }
        name = name.trim();
//        save = save + "\\" + name + type;
        save = save + "\\" + name;
        String taskid = String.valueOf(System.currentTimeMillis()) + 
                "_" + String.valueOf(Math.random() * 10000);
        saveTask(taskid, name, url, save);
        ttm.addTaskModel(new TaskModel(taskid, name, url, save));
        jTable.updateUI();
    }
    
    /**
     * 添加新的下载任务, 使用默认的保存目录
     * @param name 文件名
     * @param url 下载源
     * @throws 
     */
    public void addTask(String name, String url) {
        addTask(name, url, null);
    }
    
    public void addTaskSid(String name, String url,String sid,String action) {
        addTask(name, url, null,sid,action);
    }
    
    /**
     * 添加新的下载任务,方法同时生成一个唯一任务id 增加了SID 
     * @param name 文件名
     * @param url 下载源
     * @param save 保存目录
     */
    public synchronized void addTask(String name, String url, String save,String sid,String action) {
    	System.out.println("URL:"+url);
        String type = url.substring(url.lastIndexOf("."));
        if (null == save || "".equals(save)) {
            File musics = new File("idownloads");
            if (!musics.exists()) {
                musics.mkdirs();
            }
            save = musics.getAbsolutePath();
        }
        name = name.trim();
//        save = save + "\\" + name + type;
        save = save + "\\" + name;
        String taskid = String.valueOf(System.currentTimeMillis()) + 
                "_" + String.valueOf(Math.random() * 10000);
        saveTask(taskid, name, url, save,sid,action);
//        ttm.addTaskModel(new TaskModel(taskid, name, url, save));
        System.out.println(" thread end:");
        ttm.addTaskModel(new TaskModel(taskid, name, url, save,sid,action));
        jTable.updateUI();
    }
    
    /** 移除任务，通过任务id */
    public void removeTask(String taskid) {
        ttm.removeByTaskid(taskid);
    }
    
    /** 开始下载任务 */
    public void startTask(TaskModel task) {
        task.toStart();
    }
    
    public void pauseTask(TaskModel task) {
        task.toPause();
    }
    
    /** 停止任务 */
    public void stopTask(TaskModel task) {
        task.toStop();
    }
    
    /** 删除任务 */
    public void deleteTasks(List<TaskModel> tasks) {
        ttm.removeTasks(tasks); // 先从jTable1表格中移除
        System.out.print("this is deleteTaskTasks step1");
        for (TaskModel tm : tasks) {
        	 System.out.print("enter into for 循环");
            if (tm.toDelete()) {//edit 删除了"!"
            	//TODO 如何解决不删除 config_文件问题
            	System.out.println("2");
                removeTask(tm.getTaskid());     // 除出窗格jTable
                System.out.println("3");
                try {// 偿试删除状态文件或未完成的下载文件
                    tm.toStop();
                    Config config = getConfig(tm.getTaskid()); 
                    System.out.println("4"+config.toString());
                    System.out.println("config");
                    File processFile = new File(config.getSave() + "_");
                    System.out.println("这个文件应该删除：config.getSave_ "+config.getSave());
                    config.delete();
                    processFile.delete();
                } catch (Exception e) {
                } 
            }
            deleteConfig(tm.getTaskid());   // 删除任务列表
            //add by pope 20080806
            //TODO 增加删除文件
            
            //add by pope 20080806 end
        }
    }
    
    // -------------------------------------------------- 载入任务或创建新任务记录
    private File tasksFile; // 任务列表文件的保存路径
    private Document doc;   // tasksFile的document对象
    
    /** 载入任务列表 */
    public void loadTasks() {
            NodeList nTasks = doc.getElementsByTagName("task");
            int len = nTasks.getLength();
            for (int i = 0; i < len; i++) {
                Element eTask = (Element) nTasks.item(i);
                String config = eTask.getAttribute("config");
                if (null != config && !"".equals(config)) {  // 优先使用状态文件
                    try {
                        Config c = ConfigFactory.loadConfig(config);
                        ttm.addTaskModel(new TaskModel(c));
                    } catch (Exception e) { // 如果状态文件仍未建立
                        String id = eTask.getAttribute("id");
                        String name = eTask.getAttribute("name");
                        String url = eTask.getAttribute("url");
                        String save = eTask.getAttribute("save");
                        ttm.addTaskModel(new TaskModel(id, name, url, save));
                    } 
                } else {
                    String id = eTask.getAttribute("id");
                    String name = eTask.getAttribute("name");
                    String url = eTask.getAttribute("url");
                    String save = eTask.getAttribute("save");
                    ttm.addTaskModel(new TaskModel(id, name, url, save));
                }
            }
    }
    
    /** 保存下载文件的记录 */
    private void saveTask(String id, String name, String url, String save) {
        try {
            Element eTasks = doc.getDocumentElement();
            Element eTask = doc.createElement("task");
            eTask.setAttribute("id", id);
            eTask.setAttribute("config", (save + "_"));
            eTask.setAttribute("name", name);
            eTask.setAttribute("url", url);
            eTask.setAttribute("save", save);
            eTasks.appendChild(eTask);
            XmlOper.saveDocument(doc, tasksFile);
        } catch (Exception e) {
            Elog.log("保存创建任务信息时遇到错误：" + 
                    this.getClass().getName() + ":saveTask");
        }
    }
    
    
    /** 保存下载文件的记录 增加产品 sid */
    private void saveTask(String id, String name, String url, String save,String sid,String action) {
        try {
            Element eTasks = doc.getDocumentElement();
            Element eTask = doc.createElement("task");
            eTask.setAttribute("id", id);
            eTask.setAttribute("config", (save + "_"));
            eTask.setAttribute("name", name);
            eTask.setAttribute("url", url);
            eTask.setAttribute("save", save);
            eTask.setAttribute("sid", sid);
            eTask.setAttribute("action",action);
            eTasks.appendChild(eTask);
            XmlOper.saveDocument(doc, tasksFile);
        } catch (Exception e) {
            Elog.log("保存创建任务信息时遇到错误：" + 
                    this.getClass().getName() + ":saveTask");
        }
    }
    
    /**
     * 通过任务ID获取其配置信息（状态保存信息）,如果Config信息还不存在，则返回null.
     * Config文件只有在首次运行下载任务之后才会创建。在任务首次运行之前只会创建任务
     * 的记录，而不会创建任务的状态文件（Config)
     * @param taskid
     * @return config
     */
    public Config getConfig(String taskid) {
        String configPath = null;
        Element e = doc.getDocumentElement();
        NodeList nTasks = e.getElementsByTagName("task");
        int len = nTasks.getLength();
        for (int i = 0; i < len; i++) {
            Element eTask = (Element) nTasks.item(i);
            if (eTask.getAttribute("id").equals(taskid)) {
                configPath = eTask.getAttribute("config");
                break;
            }
        }
        if (configPath != null && !configPath.equals("")) {
            try {
                return ConfigFactory.loadConfig(configPath);
            } catch (Exception exception) {
                return null;
            }
        }
        return null;
    }
    
    /** 更新状态文件的路径保存信息, 只更新相应的tasks.xml中的相同id,的config属性*/
    public void updateConfigPath(Config config) {
        Element e = doc.getDocumentElement();
        NodeList nTasks = e.getElementsByTagName("task");
        int len = nTasks.getLength();
        for (int i = 0; i < len; i++) {
            Element eTask = (Element) nTasks.item(i);
            if (eTask.getAttribute("id").equals(config.getId())) {
                eTask.setAttribute("config", config.getConfigPath());
                eTask.setAttribute("save", config.getSave());
                break;
            }
        }
        try {
            XmlOper.saveDocument(doc, tasksFile);   // 更新后保存
        } catch (Exception ex) {
            Elog.log("更新Config文件路径是遇到问题!" +
                    "通常是由于遇到相同文件名时需要重新命名文件信息所致:" + 
                    getClass().getName());
        }
    }
    
    /** 通过任务标识ID删除任务记录 */
    public void deleteConfig(String taskid) {
        Element eTasks = doc.getDocumentElement();
        NodeList nTasks = eTasks.getElementsByTagName("task");
        int len = nTasks.getLength();
        for (int i = 0; i < len; i++) {
            Element eTask = (Element) nTasks.item(i);
            if (eTask.getAttribute("id").equals(taskid)) {
                eTasks.removeChild(eTask);
                break;
            }
        }
        try {
            XmlOper.saveDocument(doc, tasksFile);
        } catch (Exception e) {
            Elog.log("移除任务时遇到问题:" + getClass().getName());
        }
    }

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}
    
}
